#include <string>
#include <iostream>
#include <cstring>
#include <map>
#include <sstream>

#include "../include/subscriber.h"

std::map<std::string, size_t> marketData;
std::vector<quotation> quotes;

MarketDataSubscriber::MarketDataSubscriber(std::string tBrokerID, std::string tUserID, std::string tPassword, std::string tQuoteAddress, char* tInstruments[], int tSize)
{
    brokerID = tBrokerID;
    userID = tUserID;
    password = tPassword;
    instruments = tInstruments;
    size = tSize;
    ready = false;
    mdApi = CThostFtdcMdApi::CreateFtdcMdApi();
    std::cout<<"Register SPI"<<std::endl;
    mdApi->RegisterSpi(this);
    std::cout<<"Register front: "<<tQuoteAddress<<std::endl;
    mdApi->RegisterFront(const_cast<char*>(tQuoteAddress.data()));
    std::cout<<"Init start"<<std::endl;
    mdApi->Init();
}

void MarketDataSubscriber::OnFrontConnected()
{
    std::cout<<"MarketData::Front connected."<<std::endl;
    reqtime = std::chrono::steady_clock::now();
    CThostFtdcReqUserLoginField re = {0};
    // strcpy(re.BrokerID, this->brokerID.data());
    strcpy(re.UserID, this->userID.data());
    strcpy(re.Password, this->password.data());
    mdApi->ReqUserLogin(&re, 1);
}

void MarketDataSubscriber::OnFrontDisconnected(int Reason)
{
    std::cout << "MarketData::Disconnected: " << Reason << std::endl;
}

void MarketDataSubscriber::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    rsptime = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(rsptime - reqtime);
    std::cout << "MarketData::resptime: " << duration.count() << " milliseconds" << std::endl;
    std::cout << "MarketData::login errorCode: "<< pRspInfo->ErrorID<<": "<<pRspInfo->ErrorMsg<<"\n";
    SubscribeMDList(instruments, size);
}

void MarketDataSubscriber::SubscribeMDList(char* instrumentList[], int size)
{
    mdApi->SubscribeMarketData(instrumentList, size);
}

void MarketDataSubscriber::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData)
{
    std::cout<<"Handle in depth data."<<std::endl;   
    HandleIndepthMarketData(*pDepthMarketData);
}

void MarketDataSubscriber::OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    std::cout<<"On subscribe market data: "<< pSpecificInstrument->InstrumentID <<":"<<pRspInfo->ErrorID <<" - "<<pRspInfo->ErrorMsg <<std::endl;
}

void MarketDataSubscriber::HandleIndepthMarketData(CThostFtdcDepthMarketDataField &depthMarketData)
{   
    std::ostringstream os;
    os << depthMarketData.InstrumentID << "," << depthMarketData.ExchangeInstID << "," << depthMarketData.AskPrice1 << "," << depthMarketData.AskVolume1 << "," << depthMarketData.BidPrice1 << "," << depthMarketData.BidVolume1 << "," << depthMarketData.Volume << "\n";
    std::cout<<os.str()<<"\n";
}
